#ifndef BSSOCKET_MANAGER_H_
#define BSSOCKET_MANAGER_H_

#include "Common.h"
#include "Resource.h"
#include "ResourceManager.h"
#include "Singleton.h"
#include "String.h"
#include "BSSocket.h"
#include "Threading/ThreadStarter.h"
#include "Threading/QueueThreadPool.h"
#include "BufferPools.h"


class  PacketElement :public Object
{
public:
        PacketElement() {}
        virtual ~PacketElement(void);

        void Virtual_Constructor();
        void Virtual_Destructor();

        BSSocketPtr  socket;
        WorldPacket  packet;
};

#ifndef _SOCKET_MANANGER_DEFINE
#define _SOCKET_MANANGER_DEFINE

#define  DEFAULT_SERVER_REQUEST_POOL_SIZE               4096  //default main request queue size
#define WGS_SOCKET_MANAGER_MUTEX_NAME socket_manager_mutex
#define WGS_SOCKET_MANAGER_MUTEX mutable boost::mutex WGS_SOCKET_MANAGER_MUTEX_NAME;
#define WGS_SOCKET_MANAGER_LOCK         boost::lock_guard<boost::mutex>  wgsSocketManagerMutexLock(WGS_SOCKET_MANAGER_MUTEX_NAME);

#define WGS_SOCKET_MANAGER_RW_MUTEX_NAME      socket_manager_read_write_shared_mutex
#define WGS_SOCKET_MANAGER_RW_MUTEX   mutable boost::shared_mutex WGS_SOCKET_MANAGER_RW_MUTEX_NAME;
#define WGS_SOCKET_MANAGER_READ_LOCK             boost::shared_lock<boost::shared_mutex>  wgsSocketSharedMutexLock(WGS_SOCKET_MANAGER_RW_MUTEX_NAME);
#define WGS_SOCKET_MANAGER_WRITE_LOCK             boost::unique_lock<boost::shared_mutex>  wgsSocketWriteMutexLock(WGS_SOCKET_MANAGER_RW_MUTEX_NAME); 

#define WGS_WEBSOCKET_MANAGER_MUTEX_NAME websocket_manager_mutex
#define WGS_WEBSOCKET_MANAGER_MUTEX mutable boost::mutex WGS_WEBSOCKET_MANAGER_MUTEX_NAME;
#define WGS_WEBSOCKET_MANAGER_LOCK         boost::lock_guard<boost::mutex>  wgsWebSocketManagerMutexLock(WGS_WEBSOCKET_MANAGER_MUTEX_NAME);

/*
 *  Socket 关闭锁
 */
#define WGS_SOCKET_CLOSE_MUTEX_NAME socket_manager_close_mutex
#define WGS_SOCKET_CLOSE_MUTEX  mutable boost::mutex WGS_SOCKET_CLOSE_MUTEX_NAME;
#define WGS_SOCKET_CLOSE_LOCK         boost::lock_guard<boost::mutex>  wgsSocketCloseMutexLock(WGS_SOCKET_CLOSE_MUTEX_NAME);

#endif

class  BSSocketManager: public ThreadRunableBase,public ResourceManager,public Singleton<BSSocketManager>
{
	WGS_SOCKET_MANAGER_MUTEX
	WGS_SOCKET_MANAGER_RW_MUTEX
public:
	BSSocketManager();
	~BSSocketManager();

	
	ResourcePtr  create(int fd,const NameValuePairList* params = 0);

	//user manager start
	void	Startup(const uint32 &group_id,const uint32 & client_limit,const uint32 & client_timeout,const uint32 & ip_limit=0 ,const uint32 & a_limit=0, \
		const uint32 & b_limit=0, const uint32 & c_limit=0);

	void	InitThreadPool(const uint32 & thread_min,const uint32 & thread_max,const uint32 & timeout);


	void	Listen(const char * ListenAddress, uint32 Port);

	void 	Shutdown(void);

	bool     checkFlood(const uint32 & ip);

	void 	ShowStats(void);
	size_t	getSocketList(std::list<ResourcePtr> & sList);

	size_t  getSocketCount(void);


	//链接自动更新
	void	Update(const uint32 & p_time);

	//virual from  ThreadRunableBase
        bool  run(void *p);


	void AddSocket(cBSSocket * s);
	void RemoveSocket(cBSSocket * s);

	void WantWrite(cBSSocket * s);
	void WantRead(cBSSocket * s);
	void MessageLoop();
	
protected:
	uint32		m_group_id;
	
	int 		m_epoll_fd;

	uint32		m_ip_limit;
	uint32		m_net_a_limit;
	uint32		m_net_b_limit;
	uint32		m_net_c_limit;

	uint32		m_client_num_limit;

	uint32		m_client_timeout;

	std::map<uint32,uint32>			m_net_a_map;
	std::map<uint32,uint32>			m_net_b_map;
	std::map<uint32,uint32>			m_net_c_map;
	std::map<uint32,uint32>			m_ip_map;

	void	 registerFlood(const uint32 & ip);
	void	 unRegisterFlood(const uint32 & ip);

	//网络包内存分配池
	//the request queue pool
        tPPoolClass<PacketElement,DEFAULT_SERVER_REQUEST_POOL_SIZE>     m_PacketPool;

	//网络线程请求池
	//server main process threadpool
        CQueueThreadPool<PacketElement> m_processPool;

	//启动网络数据传送线程
	void SpawnNetworkThreads(void);

	String	getSocketStringName(const uint32 & serial);
       /// @copydoc ResourceManager::createImpl
        Resource* createImpl(const String& name, ResourceHandle handle,
            const String& group, bool isManual, ManualResourceLoader* loader,
            const NameValuePairList* createParams);
};

class NetworkEngineThread : public ThreadBase
{
        BSSocketManager * bsm;
public:
        NetworkEngineThread(BSSocketManager * s) :ThreadBase("NetworkEngineThread"),bsm(s) {}
        bool run()
        {
                bsm->MessageLoop();
                return true;
        }
};



#define   sBSSocketMgr	   BSSocketManager::getSingleton()

#endif 
